<?php


namespace app\common\service\store;


use AlibabaCloud\SDK\OSS\OSS\GetBucketWebsiteResponse\websiteConfiguration\routingRules\routingRule\redirect\mirrorHeaders\set;
use app\admin\model\bargain\Bargain;
use app\admin\model\bargain\BargainStore;
use app\admin\model\bargain\BargainUser;
use app\admin\model\bargain\BargainUserHelp;
use app\admin\model\store\GoodsSku;
use app\admin\model\store\SeckillConfig;
use app\api\controller\wechat\Course;
use app\common\service\BaseService;
use app\common\service\lib\QrcodeImg;
use app\common\service\wechat\WechatService;
use app\event\BargainUserInvalid;
use think\db\Query;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Event;

class BargainService extends BaseService
{
    /**
     * Author: Zhongyuan Lu
     * 砍价算法
     * @param $person int 限制的人数
     * @param $total int 要砍的金额
     * @param $max float 最大值
     * @param $min float 最小值
     * @param int $level 生成次数
     * @return array|bool
     */
    public static function barginAlgor($person, $total, $max, $min, $level = 0)
    {
        $price = $total;
        if ($level > 1000) {
            return false;
        }
        $arr = [];
        for ($i = 0; $i < $person - 1; $i++) {
            $arr[$i] = mt_rand($min * 100, $max * 100) / 100;
            $price = $price - $arr[$i];
        }
        //最后一个人砍掉剩余的金额
        $arr[$person - 1] = $price;
        if ($price < $min || $price > $max) {
            $arr = self::barginAlgor($person, $total, $max, $min, $level + 1);
        }
        return $arr;
    }

    /**
     * Author:Zhongyuan Lu
     * 创建砍价商品
     * @param $post
     * @return array
     */
    public static function createBargainGoods($post)
    {
        $sku_ids = [];
        if (strpos($post['sku_id'], ',')) {
            $sku_ids = explode(',', $post['sku_id']);
        }

        try {
            $post['start_time'] = strtotime($post['start_time']);
            $post['end_time'] = strtotime($post['end_time']);
            //单商品
            if (empty($sku_ids)) {
                Bargain::create($post);
            } else {
                //多商品
                foreach ($sku_ids as $k => $v) {
                    $data[$k] = $post;
                    $data[$k]['sku_id'] = $v;
                }
                $bargainModel = new Bargain();
                $bargainModel->saveAll($data);
            }
            return self::success('添加成功');
        } catch (\Exception $exception) {
            return self::fail($exception->getMessage());
        }
    }

    /**
     * Author:Zhongyuan Lu
     * 生成用户砍价邀请二维码
     * @param $spread_code
     * @return array
     */
    public static function generateQcCode($spread_code)
    {
        $qrCode = new QrcodeImg();
        $url = config("url.domain") . config("url.bargainUserHelp") . "?spread_code={$spread_code}";
        $spread_qrcode = $qrCode->index($url);
        return self::success('success', $spread_qrcode);
    }

    /**
     * Author:Zhongyuan Lu
     * 获取砍价商品列表
     * @param $page
     * @param $limit
     * @return array|\think\Paginator
     * @throws \think\db\exception\DbException
     */
    public static function getBargainList($page, $limit, $uid)
    {
        $time = time();
        $where = [
            ['stock', '>', 0],
            ['start_time', '<', $time],
            ['end_time', '>', $time],
        ];
        $bargainUserWhere = [
            ['uid', '=', $uid],
            ['status', 'in', [2,4]],
            ['end_time', '>', $time],
        ];
        $bargain_ids = BargainUser::where($bargainUserWhere)->column('bargain_id');
        $where[] = ['id','not in',$bargain_ids];
        $field = ['id', 'bargain_price', 'image', 'price', 'end_time', 'title'];

        $data = Bargain::where($where)->field($field)->order('sort desc')->paginate($limit);
        $data && $data = $data->toArray();
        $data['data'][0]['end_time'] = date('Y-m-d h:i:s', $data['data'][0]['end_time']);
        return $data;
    }

    /**
     * Author:Zhongyuan Lu
     * 获取砍价活动详情
     * @param $bargain_id
     * @return array
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getBargainDetail($bargain_id)
    {
        $redis = Cache::store('redis');
        $redis->select(1);
        $bargainInfo = $redis->get("bargain:bargainDetail:{$bargain_id}");
        if (!empty($bargainInfo)) {
            return self::success('success', $bargainInfo);
        }
        $where = [
            ['id', '=', $bargain_id],
            ['stock', '>', 0],
            ['start_time', '<', time()],
            ['end_time', '>', time()],
        ];
        $field = ['id', 'sku_id', 'bargain_price', 'image', 'price', 'title', 'end_time'];
        $bargainInfo = Bargain::with(['goodsSku', 'goodsSku.goods'])->where($where)->field($field)->find();
        $bargainInfo && $bargainInfo = $bargainInfo->toArray();
        $bargainInfo['goodsSku']['attr_values'] = json_decode($bargainInfo['goodsSku']['attr_values']);
        $time = $bargainInfo['end_time'] - time();
        $redis->set("bargain:bargainDetail:{$bargain_id}", $bargainInfo);
        $redis->expire("bargain:bargainDetail:{$bargain_id}", $time);

        return self::success('success', $bargainInfo);
    }

    /**
     * Author:Zhongyuan Lu
     * 查询用户是否有该商品的砍价记录
     * @param $bargainId
     * @param $userId
     * @param $end_time int 活动结束时间
     * @return array
     */
    public static function isBargainUser($bargainId, $userId, $end_time = 0)
    {
        $where = [
            ['uid', '=', $userId],
            ['bargain_id', '=', $bargainId]
        ];
        //查询用户的砍价商品记录
        $bargainUser = BargainUser::whereFind($where);
        $bargainUser && $bargainUser = $bargainUser->toArray();
        if (empty($bargainUser)) {
            return self::fail('无此数据');
        }
        if (empty($end_time)) {
            $end_time = Bargain::where('id', $bargainId)->value('end_time');
        }
        //如果用户砍价记录结束时间 小于 活动结束时间 则以活动结束时间为准
        if ($bargainUser['end_time'] > $end_time) {
            $bargainUser['end_time'] = $end_time;
        }
        //如果活动时间结束  那么用户砍价终止
        if ($bargainUser['end_time'] < time()) {
            $data['bargain_id'] = $bargainId;
            $data['uid'] = $userId;
            $bargainUser['status'] = 2;
            Event::listen('BargainUserInvalid', \app\listener\BargainUserInvalid::class);
            event($bargainId, $userId);
        }

        return self::success('success', $bargainUser);
    }

    /**
     * Author:Zhongyuan Lu
     * 查询受邀用户是否帮砍
     * @param $uid
     * @param $bargain_id
     * @param $bargainUserId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getHelpStatus($uid,$bargain_id,$bargainUserId)
    {
        $where = [
            ['uid','=',$uid],
            ['bargain_id','=',$bargain_id],
            ['bargain_user_id','=',$bargainUserId],
        ];
        $data = BargainUserHelp::where($where)->find();
        $data && $data = $data->toArray();
        if (!empty($data)) {
            return self::fail('看看其他商品');
        }
        return self::success('帮好友砍一刀');
    }

    /**
     * Author:Zhongyuan Lu
     * 砍价接口
     * @param $params
     * @param $userId
     * @return array
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function bargain($params, $userId)
    {
        //保留当前用户id
        $uid = $userId;
        if (!empty($params['bargain_user_id'])) {
            $userId = $params['bargain_user_id'];   //发起人id
        }
        $sku_id = Bargain::where('id',$params['bargain_id'])->value('sku_id');

        $redis = Cache::store('redis');
        $redis->select(1);
        //查询活动是否结束  砍价活动id
        $data = self::isEnd($params['bargain_id'], $userId);
        if ($data['code'] !== 200) {
            return self::fail($data['message']);
        }
        $bargain = $data['data'];
        $key = "bargain:{$bargain['id']}:user:{$userId}";
        //判断发起人是否参与砍价活动 $params['bargain_id']砍价活动id
        $bargainUser = self::isBargainUser($params['bargain_id'], $userId, $bargain['end_time']);
        //用户自己先砍一刀
        if ($bargainUser['code'] == 400) {
            $bargainUser = self::firstBargain($bargain, $userId, $key);
            if ($bargainUser['code'] !== 200) {
                return self::fail($bargainUser['message']);
            }
        }
        $bargainUser = $bargainUser['data'];

//        //判断用户是否帮砍过
//        $where = [
//            ['uid','=',$uid],
//            ['bargain_user_id','=',$bargainUser['id']],
//        ];
//
//        $bargainUserHelp = BargainUserHelp::where($where)->find();
//        if (!empty($bargainUserHelp)) {
//            return self::fail('已参与砍价，不能重复参与');
//        }

        if ($bargainUser['status'] !== 1) {
            return self::fail('砍价已结束');
        }

        //砍价金额
        $bargain_price = $redis->rpop($key);
        if (empty($bargain_price)) {
            return self::fail('砍价已完成');
        }

        //启动事务
        self::beginTrans();
        try {
            $price = $bargainUser['price'] - $bargain_price;

            $help = [
                'uid' => (int)$uid, //帮砍人id
                'bargain_id' => (int)$bargainUser['id'],    //发起人参与砍价活动记录id
                'bargain_user_id' => (int)$userId,   //发起人id
                'price' => (float)$bargain_price,
            ];
            //创建好友帮砍记录 更新用户砍价商品的已砍金额
            BargainUserHelp::create($help);
            $updateData['price'] = $price;
            if ($price <= 0) {
                $updateData['status'] = 3;
            }
            BargainUser::where('id', $bargainUser['id'])->update($updateData);

            self::commitTrans();
            $ret = [
                'uid' => (int)$userId,    //发起人id
                'bargain_id' => (int)$params['bargain_id'],    //砍价活动id
                'bargain_user_id' => (int)$bargainUser['id'],    //发起人参与砍价活动记录id
                'bargain_user_help_id' => (int)$uid,  //帮砍人id
                'sku_id' => $sku_id,
            ];

            //公众号
//            WechatService::bargainNotice($ret);
            if ($price == 0) {
                return self::success('砍价成功,您已经可以下单了', [], 200);
            }

            return self::success('砍价成功,邀请好友继续帮砍', [], 200);

        } catch (\Exception $exception) {
            self::rollbackTrans();
            $redis->lpush($key, $bargain_price);
            return self::fail('砍价失败');
        }
    }

    /**
     * Author:Zhongyuan Lu
     * 第一次砍价 创建砍价记录 生成用户需要砍价的金额队列
     * @param $bargain
     * @param $userId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function firstBargain($bargain, $userId, $key)
    {
        $redis = Cache::store('redis');
        $redis->select(1);
        //创建用户砍价记录
        $result = self::createBargainUser($bargain, $userId);
        if ($result['code'] !== 200) {
            return self::fail($result['message']);
        }
        $person = $bargain['bargain_num'];
        $total = floatval($bargain['price']) - floatval($bargain['bargain_price']);
        $max = (float)$bargain['bargain_max_price'];
        $min = (float)$bargain['bargain_min_price'];

        //创建用户需要砍价的金额数组
        $data = self::barginAlgor($person, $total, $max, $min);
        if ($data == false) {
            BargainUser::destroy($result['data']['id'], true);
            return self::fail('网络波动，请稍后重试');
        }
        foreach ($data as $v) {
            $redis->lpush($key, $v);
        }
        return self::success('砍价金额队列创建成功', $result['data']);
    }

    /**
     * Author:Zhongyuan Lu
     * 根据用户砍价邀请码获取记录
     * @param $spread_code
     */
    public static function getBargainUser($spread_code)
    {
        $redis = Cache::store('redis');
        $redis->select(1);
        $key = config('setting.bargainUserCode') . ":{$spread_code}";
        if (!$redis->get($key)) {
            return self::fail('未查到此砍价活动');
        }
        $data = BargainUser::whereFind(['spread_code' => $spread_code]);
        $data && $data = $data->toArray();
        if ($data) {
            return self::success('success', $data);
        }
        return self::fail('未查到次砍价活动');
    }

    /**
     * Author:Zhongyuan Lu
     * 查看砍价活动是否结束
     * @param $bargain_id
     * @return array
     */
    public static function isEnd($bargain_id, $uid)
    {
        $where = [
            ['id', '=', $bargain_id],
            ['stock', '>', 0],
            ['start_time', '<', time()],
            ['end_time', '>', time()],
        ];

        $bargain = Bargain::whereFind($where);
        $bargain && $bargain = $bargain->toArray();
        if (empty($bargain)) {
            $data['bargain_id'] = $bargain_id;
            $data['uid'] = $uid;
            event('BargainUserInvalid', $data);
            return self::fail('砍价活动时间结束');
        }
        return self::success('砍价活动进行中', $bargain);
    }

    /**
     * Author:Zhongyuan Lu
     * 修改用户砍价状态
     * @param $bargain_id
     * @param $uid
     * @return array
     */
    public static function bargainUserInvalid($bargain_id, $uid)
    {
        $where = [
            ['bargain_id', '=', $bargain_id],
            ['uid', '=', $uid],
        ];
        $bargainUser = BargainUser::whereFind($where);
        $bargainUser && $bargainUser = $bargainUser->toArray();

        if (!empty($bargainUser) || $bargainUser['status'] == 1) {
            self::beginTrans();
            try {
                BargainUser::where('id', $bargainUser['id'])->update(['status' => 2, 'spread_code' => '']);
                Bargain::where('id', $bargainUser['bargain_id'])->inc('stock')->update();
                self::commitTrans();
                self::success('修改成功');
            } catch (\Exception $exception) {
                self::rollbackTrans();
                return self::fail($exception->getMessage());
            }
        }
        return self::success('修改成功');
    }

    /**
     * Author:Zhongyuan Lu
     * 创建用户砍价记录
     * @param $uid
     * @param $bargain
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function createBargainUser($bargain, $uid)
    {
        $bargainUser = [
            'uid' => $uid,
            'bargain_id' => $bargain['id'],
            //砍价金额 = 商品价格 - 砍价目标金额
            'bargain_price' => $bargain['price'] - $bargain['bargain_price'],
            'price' => $bargain['price'] - $bargain['bargain_price'],
            'start_time' => time(),
            'end_time' => strtotime('+1 day'),
            'status' => 1,

        ];
        $redis = Cache::store('redis');
        $redis->select(1);
        //生成唯一砍价邀请吗
        while (1) {
            $bargainUser['spread_code'] = create_unique(9);
            $key = config('setting.bargainUserCode') . ":{$bargainUser['spread_code']}";
            if (!$redis->get($key)) {
                break;
            }
        }
        $spread_qrcode = self::generateQcCode($bargainUser['spread_code']);
        $bargainUser['spread_qrcode'] = $spread_qrcode['data'];

        self::beginTrans();
        try {
            //加锁
            $bargainData = Bargain::lock(true)->find($bargain['id']);
            if ($bargainData['stock'] <= 0) {
                self::commitTrans();
                return self::fail('库存为空，不能参与砍价');
            }
            Bargain::where('id', $bargain['id'])->dec('stock')->update();
            $id = BargainUser::create($bargainUser)->id;
            $bargainUser['id'] = $id;
            self::commitTrans();
            $redis->set($key, 1, 24 * 60 * 60);
            return self::success('创建成功', $bargainUser);
        } catch (\Exception $exception) {
            self::rollbackTrans();
            return self::fail('创建失败');
        }
    }

    /**
     * Author:Zhongyuan Lu
     * 好友帮砍列表
     * @param $bargain_id
     * @param $limit
     * @return array
     * @throws \think\db\exception\DbException
     */
    public static function getBargainHelpPeople($bargain_id, $limit)
    {
        $data = BargainUserHelp::with('user')
            ->where('bargain_id', $bargain_id)
            ->field(['uid', 'price', 'create_time'])
            ->order('create_time desc')
            ->paginate($limit);
        $data && $data = $data->toArray();

        if (empty($data['data'])) {
            foreach ($data['data'] as &$v) {
                $v['create_time'] = date('Y-m-d h:i:s', $v['create_time']);
            }
            unset($v);
        }

        return self::success('success', $data);
    }

    /**
     * Author:Zhongyuan Lu
     * 获取skuid 和 goods_id
     * @param $id
     * @return mixed
     */
    public static function getSkuId($id)
    {
        $goods['sku_id'] = BargainStore::where('bargain_id', $id)->column('sku_id');
        $goods['goods_id'] = GoodsSku::where('id', $goods['sku_id'][0])->value('goods_id');
        return $goods;
    }

    /**
     * Author:Zhongyuan Lu
     * 获取用户自己正在砍价的商品
     * @param $page
     * @param $limit
     * @param $uid
     * @return array
     * @throws \think\db\exception\DbException
     */
    public static function getMyBargain($page,$limit,$uid)
    {
        $data = BargainUser::where('uid',$uid)->where('status', 1)->order('id desc')->paginate($limit);
        $data && $data = $data->toArray();
        return self::success('success',$data);
    }
}